package ferus.tigris.livewallpapers.mechanism;

import java.util.ArrayList;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class EarthWallpaper extends WallpaperService {

	private final Handler mHandler = new Handler();

	@Override
	public void onCreate() {
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	@Override
	public Engine onCreateEngine() {
		return new EarthEngine(this);
	}
	
/** engine class
 * 
 * @author asd
 *
 */
public class EarthEngine extends Engine {

	private final Paint mPaint = new Paint();
	private int mOffset;
	
	private final Runnable mDraw = new Runnable() {
		public void run() {
			drawFrame();
		}
	};
	
	private final Runnable mUpdate = new Runnable() {
		public void run() {
			update();
		}
	};
	private boolean mVisible;

	Gear gear;
	ArrayList<IView> views = new ArrayList<IView>();
	Background background;
	ArrayList<IGearImagesFactory> gearImagesFactories = new ArrayList<IGearImagesFactory>();
	ImagesPool pool;

	public EarthEngine(EarthWallpaper earthWallpaper) {
		final Paint paint = mPaint;
		paint.setColor(0x0);
		paint.setAntiAlias(true);
		paint.setStrokeWidth(2);
		paint.setStrokeCap(Paint.Cap.ROUND);
		paint.setStyle(Paint.Style.STROKE);
		
		pool = ImagesPool.instance(earthWallpaper);
		
		gearImagesFactories.add(new LittleMetallFullGearImagesFactory(earthWallpaper));
		gearImagesFactories.add(new LargeMetallGearImagesFactory(earthWallpaper));
		gearImagesFactories.add(new MiddleMetallGearImagesFactory(earthWallpaper));
		gearImagesFactories.add(new LittleMetallGearImagesFactory(earthWallpaper));

		gear = new Gear(gearImagesFactories.get(0));
		Point position = new Point(250, 210);
		gear.setPosition(position);

		IGear parent = gear;
		addBoltTo(position);

		parent = newGear(position, parent, .95/4, createGear(0), 0.94);
		parent = newComposeGear(position, parent, -1.78/4, createGear(2), createGear(3), 0.93);
		parent = newGear(position, parent, .92/4, createGear(1), 0.93);
		IGear hourParent = parent;
		Point hourPos = new Point(position);
		
		//secs
		parent = newGear(position, parent, Math.PI - .51, createGear(2), 0.93);
		parent = newGear(position, parent, Math.PI - .18, createGear(0), 0.94);
		//hours
		hourParent = newGear(hourPos, hourParent, Math.PI/2, createGear(0), 0.928);
		background = new Background(pool);
	}

	protected IGear newComposeGear(Point position, IGear parent, double d, IGear g1, IGear g2, double distance) {
		ComposeGear g = new ComposeGear(g1, g2);
		g1.interactWith(parent);
		addGearToScreen(position, parent, d, g, distance);
		return g2;
	}

	protected void addGearToScreen(Point position, IGear parent, double d, IGear g, double distance) {
		int x = (int) ((parent.radius()+g.radius())*Math.cos(d)*distance);
		int y = (int) ((parent.radius()+g.radius())*Math.sin(d)*distance);
		position.offset(x, y);
		g.setPosition(position);
		views.add(g);
		addBoltTo(position);
	}

	protected IGear newGear(Point position, IGear parent, double d, IGear g, double distance) {
		g.interactWith(parent);
		addGearToScreen(position, parent, d, g, distance);
		return g;
	}

	protected IGear createGear(int index) {
		return new Gear(gearImagesFactories.get(index % gearImagesFactories.size()));
	}

	protected void addBoltTo(Point position) {
		Bolt b = new Bolt(pool);
		b.setPosition(position);
		views.add(b);
	}
	
	@Override
	public void onCreate(SurfaceHolder surfaceHolder) {
		super.onCreate(surfaceHolder);
		// By default we don't get touch events, so enable them.
		setTouchEventsEnabled(true);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		mHandler.removeCallbacks(mDraw);
		mHandler.removeCallbacks(mUpdate);
	}

	@Override
	public void onVisibilityChanged(boolean visible) {
		mVisible = visible;
		if (visible) {
			drawFrame();
			update();
		} else {
			mHandler.removeCallbacks(mDraw);
			mHandler.removeCallbacks(mUpdate);
		}
	}

	@Override
	public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		super.onSurfaceChanged(holder, format, width, height);
		drawFrame();
		update();
	}

	@Override
	public void onSurfaceCreated(SurfaceHolder holder) {
		super.onSurfaceCreated(holder);
	}

	@Override
	public void onSurfaceDestroyed(SurfaceHolder holder) {
		super.onSurfaceDestroyed(holder);
		mVisible = false;
		mHandler.removeCallbacks(mDraw);
		mHandler.removeCallbacks(mUpdate);
	}

	@Override
	public void onOffsetsChanged(float xOffset, float yOffset,
			float xStep, float yStep, int xPixels, int yPixels) {
		mOffset = xPixels;
		drawFrame();
		//update();
	}
	@Override
	public void onTouchEvent(MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_MOVE) {
		} else {
		}
		drawFrame();
		super.onTouchEvent(event);
	}
	void drawFrame() {
		final SurfaceHolder holder = getSurfaceHolder();
		Canvas c = null;
		try {
			c = holder.lockCanvas();
			if (c != null) {
				drawLayers(c);
			}
		} finally {
			if (c != null) holder.unlockCanvasAndPost(c);
		}
		mHandler.removeCallbacks(mDraw);
		if (mVisible) {
			mHandler.postDelayed(mDraw, 1000 / 20);
		}
	}

	void update() {
		gear.update();
		mHandler.removeCallbacks(mUpdate);
		if (mVisible) {
			mHandler.postDelayed(mUpdate, 1000 / 50);
		}
	}
	
	void drawLayers(Canvas c) {
		c.save();
		c.translate(mOffset, 0);
		c.drawColor(0xff000000);
		
		drawBackgroundLayer(c);
		drawMiddleLayer(c);
		drawForegroundLayer(c);

		c.restore();
	}
	
	void drawBackgroundLayer(Canvas c) {
		background.drawBackground(c);
		gear.drawBackground(c);
		for(IView g: views)
			g.drawBackground(c);
	}
	
	void drawMiddleLayer(Canvas c) {
		gear.draw(c);
		for(IView g: views)
			g.draw(c);
	}
	
	void drawForegroundLayer(Canvas c) {
		gear.drawForeground(c);
		for(IView g: views)
			g.drawForeground(c);
	}

}
	
}
